package java_thinking.unit_18_IO.exercise;

import java.io.*;
import java.util.*;
import java.util.regex.Pattern;

/**
 * @Desc:   练习
 *          根据关键字找出文件中关键字出现的次数，并按出现次数排序打印
 * @author: cww
 * @DateTime: 2020-03-28 17:11
 */

public class CountKeywordInFile {


    public static void main(String[] args) throws IOException {
        testCountKeywordInFile();
    }

    /**
     * 在某个文件中找出用户指定的关键字的出现次数，并按顺序写入一个新的输出文件中
     */
    public static void testCountKeywordInFile() throws IOException {
        long step1 = System.currentTimeMillis();
        String dir = "src/maindemo/java/java_thinking/unit_18_IO/_18_1/";
        System.out.println("Please input keywords, split by space, but not `");
        // 读取用户输入
        Scanner scan = new Scanner("hashmap list arraylist linkedhashmap");
        String input = scan.nextLine();
        String[] keyword = input.split(" ");
        System.out.println("keyword : " + Arrays.toString(keyword));
        Map<String, Integer> resultMap = new HashMap<>();
        // 根据规则列出目录下所有匹配的文件
        File[] files = listFiles(dir, ".*\\.*");
        for (File file : files) {
            // 找到指定文件，并统计在文件中出现的次数
            if (file.getName().equals("TestFile.txt")) {
                System.out.println("found file: " + file.getName());
                System.out.println("loading...");
                BufferedReader reader = new BufferedReader(new FileReader(file));
                System.out.println("loading success");
                String lineStr = null;
                while((lineStr = reader.readLine()) != null) {
                    // 加上一个符号是为了避免 split 忽略分割对象结尾的一个或多个分隔符，也就是分隔符在末尾，则该项分隔符无法统计
                    lineStr += lineStr.toLowerCase()+" `";
                    // 通过 split 方式实现搜索关键字次数的功能，注意结果要减1
                    for(int i=0;i<keyword.length;i++) {
                        int matchCount = lineStr.split(keyword[i].toLowerCase()).length - 1;
                        resultMap.put(keyword[i], resultMap.get(keyword[i]) == null ? matchCount : resultMap.get(keyword[i]) + matchCount);
                    }
                }
                reader.close();
                // 排序
                List<Map.Entry<String, Integer>> resultList = new ArrayList<>();
                for(Map.Entry<String, Integer> map : resultMap.entrySet()) {
                    resultList.add(map);
                }
                Collections.sort(resultList, new Comparator<Map.Entry<String, Integer>>(){
                    @Override
                    public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
                        return o2.getValue() - o1.getValue();
                    }
                });
                System.out.println("start writing");
                long startTime = System.currentTimeMillis();
                File file1 = new File("src/maindemo/java/java_thinking/unit_18_IO/_18_1/CountResult.txt");
                if (!file.exists()) {
                    System.out.println("file is not exist, creating");
                    file1.createNewFile();
                }
                PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter("src/maindemo/java/java_thinking/unit_18_IO/_18_1/CountResult.txt", true)),true);
                for (Iterator<Map.Entry<String, Integer>> it = resultList.iterator(); it.hasNext(); ) {
                    Map.Entry<String, Integer> map = it.next();
                    writer.println(map.getKey() + ": " +map.getValue());
                }
                writer.println("--------" + System.currentTimeMillis() + "-----------------");
                writer.close();
                long endTime = System.currentTimeMillis();
                System.out.println("write complete!");
                System.out.println("count time-consuming: " + (endTime-startTime) + " ms");
                System.out.println("total time-consuming: " + (endTime - step1) + " ms");
            }


        }
    }

    public static File[] listFiles(String dir, String regex) {
        return listFiles(new File(dir), regex);
    }
    public static File[] listFiles(File file, final String regex) {
        return file.listFiles(new FilenameFilter() {
            private Pattern pattern = Pattern.compile(regex);
            @Override
            public boolean accept(File dir, String name) {
                return pattern.matcher(new File(name).getName()).matches();
            }
        });
    }

}
